﻿#pragma once

#include <iostream>
#include <mutex>
#include <list>
#include <vector>
#include <SDL.h>
#include <chrono>
#include <thread>
#include "../../ffmpeg/task/YTools.h"
extern "C"
{
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}


/// <summary>
/// 音频播放参数结构体
/// </summary>
struct YAudioSpec
{
	int freq = 44100;//音频采样率
	unsigned short format = AUDIO_S16SYS;//采样格式（位深）
	unsigned char channels = 2;//声道数
	unsigned short samples = 1024;//样本数
};

/// <summary>
/// 音频数据结构体
/// </summary>
struct YAudioData
{
	std::vector<unsigned char> data;
	int offset = 0; //偏移位置
	long long pts = 0;
};

class YAudioPlayer
{

public:
	static YAudioPlayer* Create();

	//推送数据
	virtual void Push(AVFrame* frame);

	//暂停
	virtual void Pause(bool is_pause) = 0;

	//打开音频，开始播放，并调用回调函数
	virtual bool Open(YAudioSpec& audioSpec) = 0;//纯虚函数

	virtual bool Open(AVCodecParameters* para);

	virtual bool Open(YAVParameters& para);

	virtual void Close() = 0;

	virtual void Clear()
	{
		Close();
		SetSpeed(speed_);
	}


	//获取当前的播放位置
	virtual long long cur_pts() = 0;

	/// <summary>
	/// 需要向音频缓冲区塞数据，数据塞进去后声卡会自动播放，只要有数据就会播放
	/// </summary>
	/// <param name="data"></param>
	/// <param name="size"></param>
	void Push(const unsigned char* data, int size, long long pts)
	{
		std::unique_lock<std::mutex> lock(mux_);
		audio_datas_.push_back(YAudioData());//尾部插入数据
		audio_datas_.back().pts = pts;
		audio_datas_.back().data.assign(data, data + size);//获取队列尾部对象的引用，并分配音频数据
	}

	//播放速度
	virtual void SetSpeed(float s)
	{
		speed_ = s;
		auto spec = audio_spec_;
		auto old_freq = audio_spec_.freq;
		spec.freq *= s;
		Open(spec);
		audio_spec_.freq = old_freq;
	}

	//音量
	void set_volume(int v)
	{
		volume_ = v;
	}

	//时间基数，用于生产播放进度
	void set_time_base(double b) { time_base_ = b; }

protected:
	YAudioPlayer();
	~YAudioPlayer();

	/// <summary>
	/// SDL音频播放回调函数
	/// </summary>
	/// <param name="stream">音频流缓冲区</param>
	/// <param name="len">数据长度</param>
	virtual void Callback(unsigned char* stream, int len) = 0;
	static void AudioCallback(void* userdata, unsigned char* stream, int len)
	{
		auto player = (YAudioPlayer*)userdata;
		player->Callback(stream, len);
	}

	double time_base_ = 0;
	std::list<YAudioData> audio_datas_;//音频缓冲列表
	std::mutex mux_;//互斥锁
	YAudioSpec audio_spec_;
	unsigned char volume_ = 128;// 0~128 音量
	//播放速度（倍速播放）
	float speed_ = 1.;

};
